#include "cppTutorLinkedList.h"
#include "cppTutorGlobals.h"

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

node *first, *save, *current;

CcppTutorLinkedList :: CcppTutorLinkedList ()
{
}

CcppTutorLinkedList :: ~CcppTutorLinkedList ()
{
}

void CcppTutorLinkedList :: LinkedList_main()
{
	first = NULL;
	do
	{
		printf("######       LINK LIST IMPLEMENTATION       ######\n\n");
		printf("\n1.  Insert a Value at the Start");
		printf("\n2.  Show the Linked List");
		printf("\n3.  Insert a Value at the End");
		printf("\n4.  Clear Linked List");
		printf("\n5.  Show the Number of Nodes in the Linked List");
		printf("\n6.  Insert the Value After Mentioned Node");
		printf("\n7.  Delete a Node of Linked List");
		printf("\n8.  Search a Node of Linked List");
		printf("\n9.  Sort the Linked List");
		printf("\n10. Reverse the Linked List");
		printf("\n0.  Close the application");
		printf("\n\nPlease Enter Your Choice\n");
		cin >> choice;
		switch (choice)
		{
			case 1:
	     			printf("\nEnter The Node Value To Be Inserted At The Start: \n");
					cin >> nodeValue;
             		InsertAtStart(nodeValue);
             		break;

			case 2:
	     			ShowList();
      	     		break;

			case 3:
 	     			printf("\nEnter The Node Value To Be Inserted At The End: \n");
					cin >> nodeValue;
             		InsertAtEnd(nodeValue);
             		break;

			case 4:
	     			ClearList();
      	     		break;

			case 5:
	     			printf("\n%d Nodes are available in the Linked List",CountNodes());
	     			getchar();
	     		break;

			case 6:
	     			printf("\nEnter The Position after which you  want to Insert the new value: \n");
					cin >> insertPos;
	     			if ( insertPos > CountNodes())
	     			{
	        			printf(" Node at position %d cannot be inserted. There are only"
					       " %d node(s) in the list",insertPos,CountNodes());
	     				getchar();
	     			}
	     			else
	     			{
	        			printf("\nEnter The Value To Be Inserted after %d node(s): \n",insertPos);
						cin >> nodeValue;
	        			InsertInMid(insertPos,nodeValue);
	     			}
	     		break;

			case 7:
	     			printf("\nEnter The Node Value To Be Deleted: \n");
					cin >> nodeValue;
	     			DeleteNode(nodeValue);
	     		break;

			case 8:
	     			printf("\nEnter The Node Value To Be Searched: \n");
					cin >> nodeValue;
	     			FindNode(nodeValue);
     			break;

			case 9:
			     SortList();
	     		break;

			case 10:
	     			ReverseList();
	     		break;

		}
	}
	while (choice!=0);
}

/* This function reverses the sequences of nodes in the linked list*/
void CcppTutorLinkedList :: ReverseList()
{
	node *temp;
 	current = save = first;
 	if (first == NULL)
 	{
  		printf("\a\nThere are no nodes in the Linked List.\n");
  		getchar();
 	}
 	else
 	{
  		save = NULL;
 		while (current != NULL)
  		{
   			temp = save;
   			save = current;
   			current = current->next;
   			save->next = temp;
  		}
  		first = save;
  		printf("\nThe Linked List Has Been Reversed.\n");
  		getchar();
 	}
}

/* This function will sort the linked list*/
void CcppTutorLinkedList :: SortList()
{
	int temp;
 	current = save = first;
 	if (first==NULL)
 	{
  		printf("\aThere are no nodes in the Linked List.\n");
  		getchar();
  	}
  	else
  	{
   		for (current=first;(current != NULL);current=current->next)
   		{
       			for (save=current->next;(save != NULL);save=save->next)
       			{
        			if ( current->value < save->value )
        			{
	 				temp = save->value;
	 				save->value = current->value;
	 				current->value = temp;
				}
      			}
   		}

   	printf("\nThe Linked List Has Been Sorted.\n");
   	getchar();
   	}
}

/* This function searches for a particular node value in the linked list*/
node* CcppTutorLinkedList :: FindNode(int nValue)
{
	current = first;
 	if (first == NULL)
 	{
  		printf("\a\nThere are no nodes in the Linked List.");
  		getchar();
 	}
 	else
 	{
  		while ( (current != NULL) && (current->value != nValue) )
  		current = current->next;
  		if (current->value == nValue)
  		{
   			printf("\nThe Node is available in the Linked List.\n");
   			getchar();
   			return(current);
  		}
  		else
  		printf("\nThe Node is not available in the Linked List. Please try again.\n");
 		getchar();
 	}
	return NULL;
}

/* This function deletes a node from the linked list*/
int CcppTutorLinkedList :: DeleteNode(int nValue)
{
	int undel;
 	current = first;
 	if (first == NULL)
 	{
  		printf("\a\nThere are no nodes in the Linked List.");
  		getchar();
  	}
  	else
  	{
    		while ( (current != NULL) && (current->value != nValue) )
    		{
     			save = current;
     			current = current->next;
    		}
    		if (current->value == nValue)
    		{
      			if (current == first)
      			{
        			undel = current->value;
        			current = current->next;
        			free(first);
        			first = current;
      			}
      			else
      			{
        			undel = current->value;
        			save->next = current->next;
        			free(current);
      			}

    			printf("Node with Value %d has been Deleted.",nValue);
    			getchar();
    			return(undel);
  		}
   		else
		{
     		printf("Node with value %d is not available in the Linked List. Please try again.",nValue);
			getchar();
		}
  	}
	return NULL;
}

/* This function inserts a node in the middle of the linked list*/
void CcppTutorLinkedList :: InsertInMid(int nPos,int nValue)
{
	int count=0;
 	node *temp;
 	temp = getnode();
 	temp->value = nValue;
 	temp->next = NULL;
 	current = first;
 	while (count < nPos )
 	{
  		save = current;
  		current = current->next;
  		count++;
  	}
	if (first == NULL) 
	{
		first = temp;
	}
  	else if (current == first)
  	{
   		temp->next = current;
   		first = temp;
   	}
   	else
   	{
    		temp->next = save->next;
    		save->next = temp;
   	}
}

/* This function returns the node*/
node* CcppTutorLinkedList :: getnode()
{
	node * temp;
 	temp = (node *) malloc(sizeof(node));
 	if (temp == NULL)
 	{
  		printf("\nProblem in allocating memory to the node.!\n");
  		exit(1);
  	}
  	else
	{
		return(temp);
	}
  }

/* This function calculates the number of nodes contained in the linked list*/
int CcppTutorLinkedList :: CountNodes()
{
	int count=0;
 	current = first;
 	while (current != NULL)
 	{
  		count++;
  		current = current->next;
  	}
  	return(count);
}

/* This function inserts a node at the start of the linked list*/
void CcppTutorLinkedList :: InsertAtStart(int nValue)
{
	node *temp;
 	temp = getnode();
 	temp->value = nValue;
 	temp->next = NULL;
 	if (first == NULL)
    {
		first = temp;
	}
 	else
 	{
  		temp->next = first;
  		first = temp;
  	}
}

/* This function inserts a node at the end of the linked list*/
void CcppTutorLinkedList :: InsertAtEnd(int nValue)
{
	node *temp;
 	temp = getnode();
 	temp->value = nValue;
 	temp->next = NULL;
 	if (first == NULL)
	{
    		first = temp;
	}
 	else
 	{
  		current = first;
 		while (current != NULL)
  		{
   			save = current;
   			current = current->next;
   		}
   		save->next = temp;
   	}
}

/* This function shows all the data contained in the linked list*/
void CcppTutorLinkedList :: ShowList()
{
 	current = first;
 	if (current == NULL)
	{
    		printf("\aThere are no nodes in the Linked List.\n");
	}
 	while (current != NULL)
 	{
  		printf("\n%d", current->value);
  		current = current->next;
  	}
  	getchar();
}

/* This function clears all data from the linked list*/
void CcppTutorLinkedList :: ClearList()
{
	current = first;
 	while (current != NULL)
 	{
  		current = current->next;
 		free(first);
  		first = current;
  	}
  	printf("\nLinked List has been cleared.\n");
  	getchar();
}

